//
// Created by wujehy on 2020/8/15.
//
#include <functional>
//#include <baseType.h>
//#include "DaoBase.h"
#include "SQLiteCpp/Database.h"
//#include "glog/logging.h"
#include "Logger.h"
#define LOG(INFO) gInfo
#define LOGINFO gInfo

const static int SUCCESS = 0 ;
const static int FAIL = 1 ;
typedef std::function<void(SQLite::Statement &query, void *userdata)> BindCallbackFunction;
typedef std::function<bool(SQLite::Statement &query)> ForechoCallbackFunction;
typedef std::function<int()> DataExistCallbackFunction;

inline int
db_createTablefunc(SQLite::Database *mDb, const std::string &tablename, std::string createSql, std::string indexSql)
{
    LOG(INFO) << tablename << "start ... ";
    try
    {
        const bool bExists_ = mDb->tableExists(tablename);
        if (!bExists_)
        {
            int ret = -1;
            if (!createSql.empty())
            {
                ret = mDb->exec(createSql);

            }
            if (ret > 0  )
            {
                LOG(INFO) << "create " << tablename << " , sql = " << createSql << ", success ";
            }
            ret = -1;
            if (!indexSql.empty())
            {
                ret = mDb->exec(indexSql);
            }
            if (ret == EXIT_SUCCESS)
            {
                LOG(INFO) << "create " << tablename << " , sql = " << createSql << ", success ";
            }
        } else
        {
            LOG(INFO) << " table " << tablename << " is exist !";
        }
        return SUCCESS;
    } catch (std::exception &e)
    {
        LOG(ERROR) << "SQLite " << tablename << " Error:" << e.what();
        return FAIL;
    }
}

inline int
db_exist_func(
        SQLite::Database *mDb, const std::string &tablename, std::string &exist_sql, BindCallbackFunction exist_bind,
        void *userdata)
{
    try
    {
        SQLite::Statement query(*mDb, exist_sql);
        if(exist_bind)exist_bind(query, userdata);
        int nb = 0; //= query.exec();
        if (query.executeStep())
        {
            nb = query.getColumn(0).getInt();
        }
        return nb  ;
    } catch (std::exception &e)
    {
//         xerror2 (TSF "SQLite %0  Error: %1", tablename, e.what());
        return FAIL;
    }
}

/**
 * @brief 添加 方法
 * @param mDb数据库指针
 * @param tablename  表明
 * @param exist_sql 判断存在的函数
 * @param exist_bind_func 如果 判断函数有 ? 参数 则需要用这个方法绑定数据
 * @param addSql 不存在的是插入的函数
 * @param add_bind_func 插入函数的绑定参数的回调
 * @param existCallback 数据存在的时候回调这个 函数用户定义动作
 * @param userdata 用户数据
 * @return
 */
inline int db_add_func(
        SQLite::Database *mDb, const std::string &tablename,
        std::string &exist_sql, BindCallbackFunction exist_bind_func,
        std::string &addSql, BindCallbackFunction add_bind_func,
        DataExistCallbackFunction existCallback, void *userdata = nullptr)
{
    LOG(INFO) << "start db_add_fun " << tablename ;
    try
    {
        int exist_ret = db_exist_func(mDb, tablename, exist_sql, exist_bind_func, userdata);
        if (exist_ret > 0 )
        {
            // 存在
            // 外部 实现 更新操作
            if (existCallback == nullptr)
            {
                // 没有定义直接返回错误 添加失败
                LOG(INFO)<< "data is exist and existCallback is nullptr " ;
                return EXIT_FAILURE;
            } else
            {
                LOG(INFO)<< "data is exist and call existCallback " ;
                return existCallback();
            }
        } else
        {
            // 创建
            // 插入
            LOG(INFO)<< "add start ..." ;
            LOGINFO << "sql = " << addSql.c_str();
            SQLite::Statement qurey(*mDb, addSql);

            if (add_bind_func)add_bind_func(qurey, userdata);

            int nb = qurey.exec();
            return nb ;
        }

    } catch (std::exception &e)
    {
        LOG(WARNING)<<  "SQLite "<<tablename<<" Error: "<<e.what();
        return FAIL;
    }
}


inline int
db_del_func(
        SQLite::Database *mDb, const std::string &tablename, std::string &deleteSql,
        BindCallbackFunction delete_bind_func, void *userdata = nullptr)
{
    try
    {
        SQLite::Statement query(*mDb, deleteSql);
        if (delete_bind_func)delete_bind_func( query, userdata);
        int nb = query.exec();
        LOG(INFO)<< " delete nb = "<<nb ;
        return nb  ;
    } catch (std::exception &e)
    {
        LOG(WARNING)<<  "SQLite "<<tablename<<" Error: "<<e.what();
        return FAIL;
    }
}

/**
 * @brief 查找
 * @param mDb
 * @param tablename
 * @param find_sql
 * @param find_bind_func
 * @param forechoCallbackFunction 遍历查找的结果 , 返回 false 会立即结束 , true 则 继续下一个
 * @param userdata
 * @return
 */
inline int
db_find_func(
        SQLite::Database *mDb, const std::string &tablename, std::string &find_sql, BindCallbackFunction find_bind_func,
        ForechoCallbackFunction forechoCallbackFunction, void *userdata = nullptr)
{
    try
    {
        SQLite::Statement query(*mDb, find_sql);
        if(find_bind_func)find_bind_func(query, userdata);
        int findsize = 0 ;
        while (query.executeStep())
        {
            findsize++;
            if (!forechoCallbackFunction(query))
            {
                break;
            }
        }
        return findsize;

    } catch (std::exception &e)
    {
        LOG(WARNING)<<  "SQLite "<<tablename<<" Error: "<<e.what();
        return FAIL;
    }
}


inline int db_update_func(
        SQLite::Database *mDb, const std::string &tablename,
        std::string &update_sql, BindCallbackFunction update_bind_func,
        void *userdata = nullptr)
{
    try
    {
        SQLite::Statement query(*mDb, update_sql);
        if(update_bind_func)update_bind_func(query, userdata);
        int nb = query.exec();
        return nb ;

    } catch (std::exception &e)
    {
        LOG(WARNING)<<  "SQLite "<<tablename<<" Error: "<<e.what();
        return FAIL;
    }
}